[% setvar title docs/pdds/pdd18_security.pod - Parrot's security infrastructure %]
<div id="archive-notice">
    <h3>This file is part of the Perl 6 Archive</h3>
    <p>To see what is currently happening visit <a href="http://www.perl6.org/">http://www.perl6.org/</a></p>
</div>
<div class='pod'>
<a name='NAME'></a><h1>NAME</h1>
<p>docs/pdds/pdd18_security.pod - Parrot's security infrastructure</p>
<a name='ABSTRACT'></a><h1>ABSTRACT</h1>
<p>This PDD describes the safety, security, and quota infrastructure of
Parrot.</p>
<a name='DESCRIPTION'></a><h1>DESCRIPTION</h1>
<p>There are three basic subsystems in Parrot's security system. They
are:</p>
<ul>
<li><a name='Quotas'></a>Quotas</li>
<p>To ensure that an interpreter doesn't use more CPU time, memory, or
system resources than is allowed.</p>
<li><a name='Privilege checks'></a>Privilege checks</li>
<p>To restrict access to what an interpreter can do.</p>
<li><a name='Parameter checks'></a>Parameter checks</li>
<p>To double-check bytecode parameters for basic sanity.</p>
</ul>
<p>Each of these can be enabled or disabled separately, and each has a
particular purpose. Often two or more systems will be engaged at
once, but this isn't required.</p>
<a name='Quotas'></a><h2>Quotas</h2>
<p>The purpose of a quota system is to ensure that an interpreter
doesn't use up too many resources -- usually memory and CPU, but
there may be other scarce resources, such as files, that need
managing. In a shared environment it prevents an interpreter from
hogging too many resources, either explicitly (as in a DOS attack) or
implicitly (through poor programming or poorly scheduled runs), and
preventing other interpreters from running.</p>
<a name='Privilege checks'></a><h2>Privilege checks</h2>
<p>A privilege system is used to restrict code from performing certain
actions. When privilege checking is in force you may need a
particular privilege to load a library, or open a file.</p>
<p>Each interpreter has three sets of privileges. The first set is
the <i>current</i> privilege set, which is the set of privileges
currently in force. The second set is the set of <i>authorized</i>
privileges. These are the privileges that the interpreter is
allowed to put into its current set. The third set are the <i>sub</i>
privileges. These are the privileges that a sub has intrinsic to
itself, regardless of what the interpreter privileges currently
are. (Subs with privileges attached to them are called <i>privileged
subs</i>, oddly enough).</p>
<p>An interpreter may drop any privilege it likes from the current
set. It may also at any time enable a privilege which is in the
authorized set but not in the current set. It is possible for a sub
to have a privilege in its current set which isn't in its authorized
set. Those privileges are, once dropped, gone.</p>
<p>Subroutines may also have a set of <i>required privileges</i> attached to
them. The current interpreter <b>must</b> have those privileges in its
current or sub set to call a subroutine so tagged. If the interpreter
doesn't have the privileges then a privilege violation exception is
thrown.</p>
<a name='Parameter checking'></a><h2>Parameter checking</h2>
<p>In normal operation the interpreter assumes that the bytecode that it
executes is valid -- that is, any parameters to opcodes are sane,
data structures are intact, and the world, generally, is a good
place. When parameter checking is enabled, however, we assume that
bytecode is not necessarily valid. The interpreter then, at runtime,
makes sure that all specified register numbers are within valid
range, and string and PMC structures used are valid.</p>
<a name='Feature usage'></a><h2>Feature usage</h2>
<p>Each of the three features has a separate use. Parameter checking is
most useful when executing code which may come from an unsafe source,
for example from the network. Quotas are most useful when running
code in a managed environment such as a web, database, or game server where
no one interpreter is allowed to consume too many resources and
impact the system too badly. Privileges are used when running
untrusted code in a trusted environment, again such as a database or
game server, where Parrot can't disable certain features, but must
limit their use to trusted code.</p>
<p>It's unlikely that any one of these features will be enabled
individually, though there are certainly reasons to do so. Each
feature is separately implemented, however, and as such can be taken
singly and discussed.</p>
<a name='IMPLEMENTATION'></a><h1>IMPLEMENTATION</h1>
<a name='Quotas'></a><h2>Quotas</h2>
<p>Quota management is split into two separate parts, CPU time and
everything else.</p>
<a name='CPU time'></a><h3>CPU time</h3>
<p>CPU time is managed by the runloop. There's a certain unavoidable
overhead, but there's no way around this, at least not reliably. (We may
be able to play interesting games with timer events and system event
handlers. We'll see).</p>
<a name='Everything else'></a><h3>Everything else</h3>
<p>The rest of the quotas are enforced by code scattered across the
interpreter. The memory system handles memory quotas, the IO system
handles file open and pending IO count quotas, and so on. There's not
a whole lot for this, though we should abstract out all the
high-level operations that do things which may have quotas applied so
we can wrap these functions, so as not to pay the price when quotas
aren't in force.</p>
<p>For example, rather than having checks in the memory subsystem to see
if quotas are enabled (a check that would have to be done on each
memory allocation) we should instead access the memory allocation via
a function pointer stored off the interpreter somewhere. This way
when quotas are enabled we can swap in an alternate function pointer,
one that points to a function which checks quotas before calling into
the memory subsystem.</p>
<p>This should be relatively painless as most, if not all, of the
functions which should have quotas applied to them are also functions
which embedders may wish to override, and thus already need to be
accessed indirectly.</p>
<a name='Privileges'></a><h2>Privileges</h2>
<a name='Parameter Checking'></a><h2>Parameter Checking</h2>
<p>Parameter checking is done with an alternate runloop, one where the
opcodes first check their parameters before executing. This is fairly
expensive, which is why it isn't the default mode for operations.
(The JIT may, at its choice, check parameters at JIT time). Checking
at load time is also somewhat problematic, as it is also somewhat
expensive, means the checker needs to know the signatures for ops
which may not have been loaded yet, and precludes code doing overly
clever things. (Which itself probably ought be forbidden, but that's
a separate problem).</p>
<p>The checking op variants are automatically generated by the op file
preprocessor, the same way that it generates all the other oploop
variants.</p>
<a name='ATTACHMENTS'></a><h1>ATTACHMENTS</h1>
<a name='FOOTNOTES'></a><h1>FOOTNOTES</h1>
<a name='REFERENCES'></a><h1>REFERENCES</h1>
<a name='VERSION'></a><h1>VERSION</h1>
<a name='CURRENT'></a><h2>CURRENT</h2>
<pre>    Maintainer: Dan Sugalski
    Class: Internal
    PDD Number: 18
    Version: 1.0
    Status: Developing
    Last Modified: 29 Aug 2004
    PDD Format: 1
    Language: English</pre>
<a name='HISTORY'></a><h2>HISTORY</h2>
<ul>
<li><a name='version 1'></a>version 1</li>
<p>None. First version</p>
</ul>
<a name='CHANGES'></a><h1>CHANGES</h1>
<ul>
<li><a name='Version 1.0'></a>Version 1.0</li>
<p>None. First version</p>
</ul>
</div>
